#include "database.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QThread>
#include "sm3_utils.h"

static QString getThreadConnectionName() {
    return QString("conn_%1").arg((quintptr)QThread::currentThreadId());
}

bool Database::initialize() {
    // 主线程初始化数据库结构（不在多线程中调用）
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "main");
    db.setDatabaseName("users.db");
    if (!db.open()) {
        qDebug() << "主线程数据库打开失败:" << db.lastError().text();
        return false;
    }

    QSqlQuery query(db);
    return query.exec("CREATE TABLE IF NOT EXISTS users (username TEXT PRIMARY KEY, password TEXT)");
}

bool Database::openConnectionForThread() {
    

    QString connName = getThreadConnectionName();

    if (QSqlDatabase::contains(connName)) {
        qDebug() << "当前线程已存在数据库连接：" << connName;
        return true;
    }

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connName);
    db.setDatabaseName("users.db");

    if (!db.open()) {
        qDebug() << "线程数据库打开失败:" << db.lastError().text() << "连接名:" << connName;
        return false;
    }

    QSqlQuery query(db);
    query.exec("CREATE TABLE IF NOT EXISTS files (filename TEXT PRIMARY KEY, owner TEXT);");

    qDebug() << "线程数据库连接成功：" << connName;
    return true;
}

// bool Database::validateUser(const std::string &username, const std::string &hashedPassword) {
//     QString connName = getThreadConnectionName();
//     if (!QSqlDatabase::contains(connName)) {
//         qDebug() << "validateUser: 数据库连接未注册！连接名：" << connName;
//         return false;
//     }

//     QSqlDatabase db = QSqlDatabase::database(connName);
//     if (!db.isOpen()) {
//         qDebug() << "validateUser: 数据库未打开！连接名：" << connName;
//         return false;
//     }

//     QSqlQuery query(db);
//     query.prepare("SELECT 1 FROM users WHERE username = ? AND password = ?");
//     query.addBindValue(QString::fromStdString(username));
//     query.addBindValue(QString::fromStdString(hashedPassword));
//     return query.exec() && query.next();
// }

bool Database::validateUser(const std::string &username, const std::string &password) {
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return false;
    QSqlDatabase db = QSqlDatabase::database(connName);
    if (!db.isOpen()) return false;

    QSqlQuery query(db);
    QString hashPwd = sm3_hash(QString::fromStdString(password));

    query.prepare("SELECT COUNT(*) FROM users WHERE username = ? AND password = ?");
    query.addBindValue(QString::fromStdString(username));
    query.addBindValue(hashPwd);
    if (query.exec() && query.next()) {
        return query.value(0).toInt() > 0;
    }
    return false;
}

// bool Database::addUser(const std::string &username, const std::string &hashedPassword) {
//     QString connName = getThreadConnectionName();
//     if (!QSqlDatabase::contains(connName)) {
//         qDebug() << "addUser: 数据库连接未注册！连接名：" << connName;
//         return false;
//     }

//     QSqlDatabase db = QSqlDatabase::database(connName);
//     if (!db.isOpen()) {
//         qDebug() << "addUser: 数据库未打开！连接名：" << connName;
//         return false;
//     }

//     QSqlQuery query(db);
//     query.prepare("INSERT INTO users (username, password) VALUES (?, ?)");
//     query.addBindValue(QString::fromStdString(username));
//     query.addBindValue(QString::fromStdString(hashedPassword));
//     return query.exec();
// }

bool Database::addUser(const std::string &username, const std::string &password) {
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return false;
    QSqlDatabase db = QSqlDatabase::database(connName);
    if (!db.isOpen()) return false;

    QSqlQuery query(db);
    QString hashPwd = sm3_hash(QString::fromStdString(password));

    query.prepare("INSERT INTO users (username, password, role) VALUES (?, ?, 'user')");
    query.addBindValue(QString::fromStdString(username));
    query.addBindValue(hashPwd);
    return query.exec();
}

bool Database::recordFileOwner(const std::string &filename, const std::string &username, qint64 size) {
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return false;

    QSqlDatabase db = QSqlDatabase::database(connName);
    if (!db.isOpen()) return false;

    QString uploadTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");

    QSqlQuery query(db);
    query.prepare("INSERT OR REPLACE INTO files (filename, owner, upload_time, size) VALUES (?, ?, ?, ?)");
    query.addBindValue(QString::fromStdString(filename));
    query.addBindValue(QString::fromStdString(username));
    query.addBindValue(uploadTime);
    query.addBindValue(size);
    return query.exec();
}


QStringList Database::listFilesByUser(const std::string &username) {
    QStringList list;
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return list;

    QSqlDatabase db = QSqlDatabase::database(connName);
    if (!db.isOpen()) return list;

    QSqlQuery query(db);
    query.prepare("SELECT filename FROM files WHERE owner = ?;");
    query.addBindValue(QString::fromStdString(username));

    if (query.exec()) {
        while (query.next()) {
            list << query.value(0).toString();
        }
    }
    return list;
}

bool Database::deleteFileRecord(const std::string &filename) {
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return false;

    QSqlDatabase db = QSqlDatabase::database(connName);
    if (!db.isOpen()) return false;

    QSqlQuery query(db);
    query.prepare("DELETE FROM files WHERE filename = ?");
    query.addBindValue(QString::fromStdString(filename));
    return query.exec();
}

bool Database::isAdmin(const std::string &username) {
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return false;
    QSqlDatabase db = QSqlDatabase::database(connName);
    if (!db.isOpen()) return false;

    QSqlQuery query(db);
    query.prepare("SELECT role FROM users WHERE username = ?");
    query.addBindValue(QString::fromStdString(username));
    if (query.exec() && query.next()) {
        QString role = query.value(0).toString();
        return role == "admin";
    }

    return false;
}

QList<QMap<QString, QString>> Database::listAllFiles() {
    QList<QMap<QString, QString>> files;

    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return files;

    QSqlDatabase db = QSqlDatabase::database(connName);
    if (!db.isOpen()) return files;

    QSqlQuery query(db);
    query.prepare("SELECT owner, filename, upload_time, size FROM files ORDER BY upload_time DESC");
    if (!query.exec()) return files;

    while (query.next()) {
        QMap<QString, QString> file;
        file["username"] = query.value(0).toString();     
        file["filename"] = query.value(1).toString();
        file["upload_time"] = query.value(2).toString();
        file["size"] = query.value(3).toString();
        files.append(file);
    }

    return files;
}

bool Database::userExists(const std::string &username) {
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return false;

    QSqlDatabase db = QSqlDatabase::database(connName);
    QSqlQuery query(db);
    query.prepare("SELECT COUNT(*) FROM users WHERE username = ?");
    query.addBindValue(QString::fromStdString(username));
    if (query.exec() && query.next()) {
        return query.value(0).toInt() > 0;
    }
    return false;
}

bool Database::addUserWithRole(const std::string &username, const std::string &password, const std::string &role) {
    QString connName = getThreadConnectionName();
    if (!QSqlDatabase::contains(connName)) return false;

    QSqlDatabase db = QSqlDatabase::database(connName);
    QSqlQuery query(db);
    QString hashPwd = sm3_hash(QString::fromStdString(password));

    query.prepare("INSERT INTO users (username, password, role) VALUES (?, ?, ?)");
    query.addBindValue(QString::fromStdString(username));
    query.addBindValue(hashPwd);

    // query.addBindValue(QString::fromStdString(password));
    query.addBindValue(QString::fromStdString(role));
    
    return query.exec();
}


